package com.fastloan.mgt.application.phoneapprove.service.impl;

import com.alibaba.fastjson.JSON;
import com.fastloan.common.BasicServiceImpl;
import com.fastloan.common.model.CheckResult;
import com.fastloan.mgt.application.base.enums.ApplicationStatusEnum;
import com.fastloan.mgt.application.base.model.Application;
import com.fastloan.mgt.application.base.model.ApplicationIPC;
import com.fastloan.mgt.application.base.model.ApplicationValue;
import com.fastloan.mgt.application.base.model.ApplicationValueModifyHistory;
import com.fastloan.mgt.application.base.service.ApplicationIPCService;
import com.fastloan.mgt.application.base.service.ApplicationService;
import com.fastloan.mgt.application.phoneapprove.dao.ApplicationPhoneApproveFileMapper;
import com.fastloan.mgt.application.phoneapprove.dao.ApplicationPhoneApproveMapper;
import com.fastloan.mgt.application.phoneapprove.model.ApplicationPhoneApprove;
import com.fastloan.mgt.application.phoneapprove.model.ApplicationPhoneApproveFile;
import com.fastloan.mgt.application.phoneapprove.model.vo.ApplicationPhoneApproveVo;
import com.fastloan.mgt.application.phoneapprove.service.ApplicationPhoneApproveService;
import com.fastloan.mgt.processcontrol.base.annotation.FunctionHandlerClass;
import com.fastloan.mgt.processcontrol.base.annotation.FunctionHandlerMethod;
import com.fastloan.mgt.processcontrol.base.model.ProcessSession;
import com.fastloan.mgt.processcontrol.base.service.ProcessDispatcher;
import com.fastloan.mgt.product.flow.enums.ProductFunctionGroup;
import com.fastloan.safe.core.param.RoleTypeEnum;
import com.fastloan.safe.core.util.ManagerKit;
import com.fastloan.safe.mgt.sys.model.CmuSysFile;
import com.fastloan.safe.mgt.sys.service.CmSysFileService;
import com.fastloan.safe.mgt.user.model.CmuUser;
import com.fastloan.safe.mgt.user.service.CmuUserService;
import com.kawins.supers.table.manager.DataTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

import static java.util.stream.Collectors.toList;

/**
 * @author yanwe
 * createTime 2017-11-2017/11/10 16:49
 */
@Service
@FunctionHandlerClass(processName = "电核", bmpIds = {ProductFunctionGroup.GROUP_ONE})
public class ApplicationPhoneApproveServiceImpl extends BasicServiceImpl<ApplicationPhoneApprove> implements ApplicationPhoneApproveService {

    @Autowired
    private ApplicationIPCService applicationIPCService;

    @Autowired
    private ApplicationService applicationService;

    @Autowired
    private ApplicationPhoneApproveFileMapper applicationPhoneApproveFileMapper;

    @Autowired
    private ApplicationPhoneApproveMapper applicationPhoneApproveMapper;

    @Autowired
    private CmuUserService cmuUserService;

    @Autowired
    private CmSysFileService cmSysFileService;

    public static final Integer PASS = 1;

    @Override
    @FunctionHandlerMethod
    public void phoneApprove(String processId) {
        ProcessSession processSession = ProcessDispatcher.getProcessSession(processId);
        String applicationId = processSession.getAttribute("applicationId", String.class);
        applicationService.modifyApplicationStatus(applicationId, ApplicationStatusEnum.WAIT_PHONE_APPROVE);
    }

    @Override
    public ApplicationPhoneApprove getApproveInfo(String applicationId) {
        ApplicationPhoneApprove criteria = new ApplicationPhoneApprove();
        criteria.setApplicationId(applicationId);
        List<ApplicationPhoneApprove> applicationPhoneApproveList = select(criteria);
        if (applicationPhoneApproveList.isEmpty()){
            return null;
        }
        applicationPhoneApproveList.sort(Comparator.comparing(ApplicationPhoneApprove::getApproveTime).reversed());
        ApplicationPhoneApprove applicationPhoneApprove = applicationPhoneApproveList.get(0);
        CmuUser approveUser = cmuUserService.selectByPrimaryKey(applicationPhoneApprove.getApproveUser());
        applicationPhoneApprove.setApproveUserName(approveUser.getCname());
        Application application = applicationService.selectByPrimaryKey(applicationId);
        applicationPhoneApprove.setApplicationCode(application.getApplicationCode());
        applicationPhoneApprove.setIpcModifyInfoTree(filter(applicationIPCService
                .selectApplicationIPC(applicationId)));
        applicationPhoneApprove.setFiles(getApproveFile(applicationPhoneApprove.getPhoneApproveId()));
        return applicationPhoneApprove;
    }

    @Override
    @Transactional
    public CheckResult approve(ApplicationPhoneApprove applicationPhoneApprove, MultipartFile[] files){
        applicationPhoneApprove.setApproveUser(ManagerKit.getUserId());
        applicationPhoneApprove.setApproveTime(new Date());
        saveIPCModifyHistory(applicationPhoneApprove);
        insertSelective(applicationPhoneApprove);
        upLoad(files, ApplicationPhoneApproveFile::new, applicationPhoneApprove.getPhoneApproveId())
                .entrySet().stream().map(Map.Entry::getValue)
                .forEach(applicationPhoneApproveFileMapper::insert);
        boolean isPass = PASS.equals(applicationPhoneApprove.getApproveResult());
        if (!isPass) {//未通过电核
            applicationService.modifyApplicationStatus(applicationPhoneApprove.getApplicationId()
                    , ApplicationStatusEnum.PHONE_APPROVE_REJECT);
        }
        String processId = applicationService.selectByPrimaryKey(applicationPhoneApprove.getApplicationId()).getProcessId();
        ProcessDispatcher.executeEnd(processId, isPass);
        return new CheckResult();
    }

    @Override
    @DataTable(name = "selectApplicationPhoneApproveVo")
    public List<ApplicationPhoneApproveVo> selectApplicationPhoneApproveVo(Map<String, Object> map) {
        return applicationPhoneApproveMapper.selectApplicationPhoneApproveVo(map);
    }


    @Override
    public List<String> queryFileIds(String applicationId) {
        ApplicationPhoneApprove phoneApprove = new ApplicationPhoneApprove();
        phoneApprove.setApplicationId(applicationId);
        List<ApplicationPhoneApprove> approveList = select(phoneApprove);
        List<List<String>> listList = approveList.stream()
                .map(ApplicationPhoneApprove::getPhoneApproveId)
                .map(phoneApproveId -> {
                    ApplicationPhoneApproveFile phoneApproveFile = new ApplicationPhoneApproveFile();
                    phoneApproveFile.setPhoneApproveId(phoneApproveId);
                    List<ApplicationPhoneApproveFile> phoneApproveFileList = applicationPhoneApproveFileMapper.select(phoneApproveFile);
                    return phoneApproveFileList.stream()
                            .filter(Objects::nonNull)
                            .map(ApplicationPhoneApproveFile::getFileId)
                            .collect(toList());
                }).collect(toList());
        List<String> fileIds = new ArrayList<>();
        listList.forEach(fileIds::addAll);
        return fileIds.isEmpty() ? new ArrayList<>() : fileIds;
    }

    private boolean check(ApplicationPhoneApprove applicationPhoneApprove) {
        String applicationId = applicationPhoneApprove.getApplicationId();
        ApplicationPhoneApprove criteria = new ApplicationPhoneApprove();
        criteria.setApplicationId(applicationId);
        int count = selectCount(criteria);
        return count != 0;
    }

    private List<CmuSysFile> getApproveFile(String phoneApproveId){
        ApplicationPhoneApproveFile criteria = new ApplicationPhoneApproveFile();
        criteria.setPhoneApproveId(phoneApproveId);
        List<ApplicationPhoneApproveFile> applicationPhoneApproveFiles =
                applicationPhoneApproveFileMapper.select(criteria);
        return applicationPhoneApproveFiles.stream().map(applicationPhoneApproveFile ->
                cmSysFileService.selectByPrimaryKey(applicationPhoneApproveFile.getFileId()))
                .collect(toList());
    }

    private void saveIPCModifyHistory(ApplicationPhoneApprove applicationPhoneApprove) {
        List<ApplicationIPC> modifyIPCs =
                JSON.parseArray(applicationPhoneApprove.getIpcModifyInfo(), ApplicationIPC.class);
        List<ApplicationIPC> beforeIPCs
                = applicationIPCService.selectApplicationIPC(applicationPhoneApprove.getApplicationId());
        for (ApplicationIPC beforeIPC : beforeIPCs) {
            for (ApplicationIPC modifyIPC : modifyIPCs) {
                if (beforeIPC.getProductTempId().equals(modifyIPC.getProductTempId())) {
                    List<ApplicationIPC> beforeIPCChildList = beforeIPC.getChildList();
                    List<ApplicationIPC> modifyIPCChildList = modifyIPC.getChildList();
                    for (ApplicationIPC beforeChildIPC : beforeIPCChildList) {
                        for (ApplicationIPC modifyChildIPC : modifyIPCChildList) {
                            if (beforeChildIPC.getApplicationIpcId().equals(modifyChildIPC.getApplicationIpcId())) {
                                String beforeValue = beforeChildIPC.getApplicationValue();
                                String afterValue = modifyChildIPC.getApplicationValue();
                                if (beforeValue == null || ("".equals(beforeValue) && !afterValue.equals("")) ||
                                        !beforeValue.equals(afterValue)) {
                                    ApplicationValue applicationValue = new ApplicationValue();
                                    applicationValue.setApplicationValue(modifyChildIPC.getApplicationValue());
                                    applicationValue.setApplicationIpcId(modifyChildIPC.getApplicationIpcId());
                                    applicationIPCService.updateIPC(applicationValue, null);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 过滤电核员修改的记IPC
     *
     * @param applicationIPCList 原始IPC
     * @return 过滤后的
     */
    private List<ApplicationIPC> filter(List<ApplicationIPC> applicationIPCList) {
        List<ApplicationIPC> resultList = new ArrayList<>();
        for (ApplicationIPC applicationIPC : applicationIPCList) {
            List<ApplicationIPC> childList = applicationIPC.getChildList();
            if (childList == null || childList.isEmpty()) {
                continue;
            }
            List<ApplicationIPC> filterIPCList = new ArrayList<>();
            for (ApplicationIPC ipc : childList) {
                List<ApplicationValueModifyHistory> childIPCModifyHistory
                        = ipc.getApplicationValueModifyHistoryList();
                if (childIPCModifyHistory != null && !childIPCModifyHistory.isEmpty()
                        && childIPCModifyHistory.stream().anyMatch(history ->
                        history.getRoleId().equals(String.valueOf(RoleTypeEnum.AUDITOR.getCode())))) {
                    childIPCModifyHistory.removeIf(history ->
                            !history.getRoleId().equals(String.valueOf(RoleTypeEnum.AUDITOR.getCode())));
                    filterIPCList.add(ipc);
                }
            }
            if (!filterIPCList.isEmpty()) {
                applicationIPC.setChildList(filterIPCList);
                resultList.add(applicationIPC);
            }
        }
        return resultList;
    }
}
